﻿#region << 文 件 说 明 >>

/*----------------------------------------------------------------
// 文件名称：Utils
// 创 建 者：杨程
// 创建时间：2021/9/16 11:04:27
// 文件版本：V1.0.0
// ===============================================================
// 功能描述：
//
//
//----------------------------------------------------------------*/

#endregion

//using Microsoft.Extensions.Caching.Distributed;
//using NPOI.HSSF.Util;

namespace Vampirewal.Core;

/// <summary>
///
/// </summary>
public class Utils
{
    public static string GetCurrentComma()
    {
        if (CultureInfo.CurrentUICulture.Name == "zh-cn")
        {
            return "：";
        }
        else
        {
            return ":";
        }
    }

    public static List<Assembly> GetAllAssembly()
    {
        var rv = new List<Assembly>();
        var path = Assembly.GetEntryAssembly().Location;
        var dir = new DirectoryInfo(System.IO.Path.GetDirectoryName(path));

        var dlls = dir.GetFiles("*.dll", SearchOption.AllDirectories);
        string[] systemdll = new string[]
        {
            "Microsoft.",
            "System.",
            "Swashbuckle.",
            "ICSharpCode",
            "Newtonsoft.",
            "Oracle.",
            "Pomelo.",
            "SQLitePCLRaw."
        };

        foreach (var dll in dlls)
        {
            try
            {
                if (systemdll.Any(x => dll.Name.StartsWith(x)) == false)
                {
                    rv.Add(AssemblyLoadContext.Default.LoadFromAssemblyPath(dll.FullName));
                }
            }
            catch { }
        }
        return rv;
    }

    //public static FrameworkMenu FindMenu(string url)
    //{
    //    if (url == null)
    //    {
    //        return null;
    //    }
    //    url = url.ToLower();
    //    var menus = GlobalServices.GetRequiredService<GlobalData>()?.AllMenus;
    //    if (menus == null)
    //    {
    //        return null;
    //    }
    //    //寻找菜单中是否有与当前判断的url完全相同的
    //    var menu = menus.Where(x => x.Url != null && x.Url.ToLower() == url).FirstOrDefault();

    //    //如果没有，抹掉当前url的参数，用不带参数的url比对
    //    if (menu == null)
    //    {
    //        var pos = url.IndexOf("?");
    //        if (pos > 0)
    //        {
    //            url = url.Substring(0, pos);
    //            menu = menus.Where(x => x.Url != null && (x.Url.ToLower() == url || x.Url.ToLower() + "async" == url)).FirstOrDefault();
    //        }
    //    }

    //    //如果还没找到，则判断url是否为/controller/action/id这种格式，如果是则抹掉/id之后再对比
    //    if (menu == null && url.EndsWith("/index"))
    //    {
    //        url = url.Substring(0, url.Length - 6);
    //        menu = menus.Where(x => x.Url != null && x.Url.ToLower() == url).FirstOrDefault();
    //    }
    //    if (menu == null && url.EndsWith("/indexasync"))
    //    {
    //        url = url.Substring(0, url.Length - 11);
    //        menu = menus.Where(x => x.Url != null && x.Url.ToLower() == url).FirstOrDefault();
    //    }
    //    return menu;
    //}

    /// <summary>
    /// 
    /// </summary>
    /// <param name="fieldName"></param>
    /// <returns></returns>
    public static string GetIdByName(string fieldName)
    {
        return fieldName == null ? "" : fieldName.Replace(".", "_").Replace("[", "_").Replace("]", "_");
    }

    /// <summary>
    /// 验证不同项
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="oldList">旧列表</param>
    /// <param name="newList">新列表</param>
    /// <param name="ToRemove">需移除的</param>
    /// <param name="ToAdd">需新增的</param>
    public static void CheckDifference<T>(IEnumerable<T> oldList, IEnumerable<T> newList, out IEnumerable<T> ToRemove, out IEnumerable<T> ToAdd) where T : TopModel
    {
        List<T> tempToRemove = new List<T>();
        List<T> tempToAdd = new List<T>();
        oldList ??= new List<T>();
        newList ??= new List<T>();
        foreach (var oldItem in oldList)
        {
            bool exist = false;
            foreach (var newItem in newList)
            {
                if (oldItem.GetBillID().ToString() == newItem.GetBillID().ToString())
                {
                    exist = true;
                    break;
                }
            }
            if (exist == false)
            {
                tempToRemove.Add(oldItem);
            }
        }
        foreach (var newItem in newList)
        {
            bool exist = false;
            foreach (var oldItem in oldList)
            {
                if (newItem.GetBillID().ToString() == oldItem.GetBillID().ToString())
                {
                    exist = true;
                    break;
                }
            }
            if (exist == false)
            {
                tempToAdd.Add(newItem);
            }
        }
        ToRemove = tempToRemove.AsEnumerable();
        ToAdd = tempToAdd.AsEnumerable();
    }

    //public static short GetExcelColor(string color)
    //{
    //    var colors = typeof(HSSFColor).GetNestedTypes().ToList();
    //    foreach (var col in colors)
    //    {
    //        var pro = col.GetField("hexString");
    //        if (pro == null)
    //        {
    //            continue;
    //        }
    //        var hex = pro.GetValue(null);
    //        var rgb = hex.ToString().Split(':');
    //        for (int i = 0; i < rgb.Length; i++)
    //        {
    //            if (rgb[i].Length > 2)
    //            {
    //                rgb[i] = rgb[i].Substring(0, 2);
    //            }
    //        }
    //        int r = Convert.ToInt16(rgb[0], 16);
    //        int g = Convert.ToInt16(rgb[1], 16);
    //        int b = Convert.ToInt16(rgb[2], 16);

    //        if (color.Length == 8)
    //        {
    //            color = color.Substring(2);
    //        }
    //        string c1 = color.Substring(0, 2);
    //        string c2 = color.Substring(2, 2);
    //        string c3 = color.Substring(4, 2);

    //        int r1 = Convert.ToInt16(c1, 16);
    //        int g1 = Convert.ToInt16(c2, 16);
    //        int b1 = Convert.ToInt16(c3, 16);

    //        if (r == r1 && g == g1 && b == b1)
    //        {
    //            return (short)col.GetField("index").GetValue(null);
    //        }
    //    }
    //    return HSSFColor.COLOR_NORMAL;
    //}

    ///// <summary>
    ///// 获取Bool类型的下拉框
    ///// </summary>
    ///// <param name="boolType"></param>
    ///// <param name="defaultValue"></param>
    ///// <param name="trueText"></param>
    ///// <param name="falseText"></param>
    ///// <param name="selectText"></param>
    ///// <returns></returns>
    //public static List<ComboSelectListItem> GetBoolCombo(BoolComboTypes boolType, bool? defaultValue = null, string trueText = null, string falseText = null, string selectText = null)
    //{
    //    List<ComboSelectListItem> rv = new List<ComboSelectListItem>();
    //    string yesText = "";
    //    string noText = "";
    //    switch (boolType)
    //    {
    //        case BoolComboTypes.YesNo:
    //            yesText = Program._localizer["Yes"];
    //            noText = Program._localizer["No"];
    //            break;
    //        case BoolComboTypes.ValidInvalid:
    //            yesText = Program._localizer["Valid"];
    //            noText = Program._localizer["Invalid"];
    //            break;
    //        case BoolComboTypes.MaleFemale:
    //            yesText = Program._localizer["Male"];
    //            noText = Program._localizer["Female"];
    //            break;
    //        case BoolComboTypes.HaveNotHave:
    //            yesText = Program._localizer["Have"];
    //            noText = Program._localizer["NotHave"];
    //            break;
    //        case BoolComboTypes.Custom:
    //            yesText = trueText ?? Program._localizer["Yes"];
    //            noText = falseText ?? Program._localizer["No"];
    //            break;
    //        default:
    //            break;
    //    }
    //    ComboSelectListItem yesItem = new ComboSelectListItem()
    //    {
    //        Text = yesText,
    //        Value = "true"
    //    };
    //    if (defaultValue == true)
    //    {
    //        yesItem.Selected = true;
    //    }
    //    ComboSelectListItem noItem = new ComboSelectListItem()
    //    {
    //        Text = noText,
    //        Value = "false"
    //    };
    //    if (defaultValue == false)
    //    {
    //        noItem.Selected = true;
    //    }
    //    rv.Add(yesItem);
    //    rv.Add(noItem);
    //    return rv;
    //}

    

    /// <summary>
    /// 
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    public static string EncodeScriptJson(string input)
    {
        if (input == null)
        {
            return "";
        }
        else
        {
            return input.Replace(Environment.NewLine, "").Replace("\"", "\\\\\\\"").Replace("'", "\\'");
        }
    }

    /// <summary>
    /// 删除文件
    /// </summary>
    /// <param name="path"></param>
    public static void DeleteFile(string path)
    {
        try
        {
            System.IO.File.Delete(path);
        }
        catch { }
    }

    #region 格式化文本

    /// <summary>
    /// 格式化文本
    /// </summary>
    /// <param name="text">要格式化的字符串</param>
    /// <param name="isCode">是否是纯代码</param>
    /// <returns></returns>
    public static string FormatText(string text, bool isCode = false)
    {
        if (isCode)
        {
            return FormatCode(text);
        }
        else
        {
            #region 截取需要格式化的代码段

            List<int> listInt = new List<int>();
            int index = 0;
            int _index;
            while (true)
            {
                _index = text.IndexOf("&&", index);
                index = _index + 1;
                if (_index >= 0 && _index <= text.Length)
                {
                    listInt.Add(_index);
                }
                else
                {
                    break;
                }
            }

            List<string> listStr = new List<string>();
            for (int i = 0; i < listInt.Count; i++)
            {
                string temp = text.Substring(listInt[i] + 2, listInt[i + 1] - listInt[i] - 2);

                listStr.Add(temp);
                i++;
            }

            #endregion

            #region 格式化代码段

            //先将 <  >以及空格替换掉，防止下面替换出现 html标签后出现问题
            for (int i = 0; i < listStr.Count; i++)
            {
                //将 &&代码&&  替换成&&1&&
                text = text.Replace("&&" + listStr[i] + "&&", FormatCode(listStr[i]));
            }

            #endregion

            return text;
        }
    }

    #endregion

    #region 格式化代码

    /// <summary>
    /// 格式化代码
    /// </summary>
    /// <param name="code"></param>
    /// <returns></returns>
    public static string FormatCode(string code)
    {
        //先将 <  >以及空格替换掉，防止下面替换出现 html标签后出现问题
        code = code.Replace("<", "&lt;").Replace(">", "&gt;").Replace(" ", "&nbsp;");
        string csKeyWords = "abstract|as|base|bool|break|byte|case|catch|char|checked|class|const|continue|decimal|default|delegate|do|double|else|enum|event|explicit|extern|false|finally|fixed|float|for|foreach|from|get|goto|group|if|implicit|in|int|interface|internal|into|is|join|let|lock|long|namespace|new|null|object|operator|orderby|out|override|params|partial|private|protected|public|readonly|ref|return|sbyte|sealed|select|set|short|sizeof|stackalloc|static|string|struct|switch|this|throw|true|try|typeof|uint|ulong|unchecked|unsafe|ushort|using|value|var|virtual|void|volatile|where|while|yield";

        string r1 = "(#if DBG[\\s\\S]+?#endif)";
        string r2 = "(#[a-z ]*)";
        string r3 = "(///\\ *<[/\\w]+>)";
        string r4 = "(/\\*[\\s\\S]*?\\*/)";//匹配三杠注释
        string r5 = "(//.*)";//匹配双杠注释
        string r6 = @"(@?"".*?"")";//匹配字符串
        string r7 = "('.*?')";//匹配字符串
        string r8 = "\\b(" + csKeyWords + ")\\b";//匹配关键字
        //string r9 = "class&nbsp;(.+)&nbsp;";//匹配类
        //string r10 = "&lt;(.+)&gt;";//匹配泛型类

        string rs = string.Format("{0}|{1}|{2}|{3}|{4}|{5}|{6}|{7}", r1, r2, r3, r4, r5, r6, r7, r8);
        //string rs = string.Format("{0}|{1}|{2}|{3}|{4}|{5}|{6}|{7}|{8}|{9}", r1, r2, r3, r4, r5, r6, r7, r8, r9,r10);

        //<font color=#44C796>$9$10</font>
        string rr = "<font color=#808080>$1$2$3</font><font color=#008000>$4$5</font><font color=#A31515>$6$7</font><font color=#0000FF>$8</font>";

        Regex re = new Regex(rs, RegexOptions.None);
        code = Regex.Replace(code, rs, rr);
        //替换换行符"\r\n"   以及"\r"  "\n"
        code = code.Replace("\r\n", "<br>").Replace("\n", "").Replace("\r", "<br>");
        //取消空标签
        //|<font color=#44C796></font>C#类的颜色
        code = Regex.Replace(code, "<font color=#808080></font>|<font color=#008000></font>|<font color=#A31515></font>|<font color=#0000FF></font>", "");

        return code;
    }

    #endregion

    #region 读取txt文件

    /// <summary>
    /// 读取文件
    /// </summary>
    /// <param name="path">文件路径绝对</param>
    /// <returns></returns>
    public static string ReadTxt(string path)
    {
        string result = string.Empty;

        if (File.Exists(path))
        {
            using (Stream fs = File.Open(path, FileMode.Open, FileAccess.Read, FileShare.Read))
            {
                using (TextReader sr = new StreamReader(fs, UnicodeEncoding.UTF8))
                {
                    result = sr.ReadToEnd();
                }
            }
        }

        return result;
    }

    #endregion

    /// <summary>
    /// 得到目录下所有文件
    /// </summary>
    /// <param name="dirpath"></param>
    /// <returns></returns>
    public static List<string> GetAllFileName(string dirpath)
    {
        DirectoryInfo dir = new DirectoryInfo(dirpath);
        var files = dir.GetFileSystemInfos();
        return files.Select(x => x.Name).ToList();
    }

    #region add by wuwh 2014.10.18  递归获取目录下所有文件

    /// <summary>
    /// 递归获取目录下所有文件
    /// </summary>
    /// <param name="dirPath"></param>
    /// <param name="allFiles"></param>
    /// <returns></returns>
    public static List<string> GetAllFilePathRecursion(string dirPath, List<string> allFiles)
    {
        allFiles ??= new List<string>();
        string[] subPaths = Directory.GetDirectories(dirPath);
        foreach (var item in subPaths)
        {
            GetAllFilePathRecursion(item, allFiles);
        }
        allFiles.AddRange(Directory.GetFiles(dirPath).ToList());

        return allFiles;
    }

    #endregion

    /// <summary>
    /// ConvertToColumnXType
    /// </summary>
    /// <param name="type"></param>
    /// <returns></returns>
    public static string ConvertToColumnXType(Type type)
    {
        if (type == typeof(bool) || type == typeof(bool?))
        {
            return "checkcolumn";
        }
        else if (type == typeof(DateTime) || type == typeof(DateTime?))
        {
            return "datecolumn";
        }
        else if (type == typeof(decimal) || type == typeof(decimal?) || type == typeof(double) || type == typeof(double?) || type == typeof(int) || type == typeof(int?) || type == typeof(long) || type == typeof(long?))
        {
            return "numbercolumn";
        }
        return "textcolumn";
    }

    //public static string GetCS(string cs, string mode, Configs config)
    //{
    //    if (string.IsNullOrEmpty(cs) || config.ConnectionStrings.Any(x => x.Key.ToLower() == cs.ToLower()) == false)
    //    {
    //        cs = "default";
    //    }
    //    int index = cs.LastIndexOf("_");
    //    if (index > 0)
    //    {
    //        cs = cs.Substring(0, index);
    //    }
    //    if (mode?.ToLower() == "read")
    //    {
    //        var reads = config.ConnectionStrings.Where(x => x.Key.StartsWith(cs + "_")).Select(x => x.Key).ToList();
    //        if (reads.Count > 0)
    //        {
    //            Random r = new Random();
    //            var v = r.Next(0, reads.Count);
    //            cs = reads[v];
    //        }
    //    }
    //    return cs;
    //}

    //public static string GetUrlByFileAttachmentId(IDataContext dc, Guid? fileAttachmentId, bool isIntranetUrl = false, string urlHeader = null)
    //{
    //    string url = string.Empty;
    //    var fileAttachment = dc.Set<FileAttachment>().Where(x => x.ID == fileAttachmentId.Value.ToString()).FirstOrDefault();
    //    if (fileAttachment != null)
    //    {
    //        url = "/_Framework/GetFile/" + fileAttachmentId.ToString();

    //    }
    //    return url;
    //}

    #region 加解密

    /// <summary>
    /// 通过密钥将内容加密
    /// </summary>
    /// <param name="stringToEncrypt">要加密的字符串</param>
    /// <param name="encryptKey">加密密钥</param>
    /// <returns></returns>
    public static string EncryptString(string stringToEncrypt, string encryptKey)
    {
        if (string.IsNullOrEmpty(stringToEncrypt))
        {
            return "";
        }

        string stringEncrypted = string.Empty;
        byte[] bytIn = UTF8Encoding.UTF8.GetBytes(stringToEncrypt);
        MemoryStream encryptStream = new System.IO.MemoryStream();
        CryptoStream encStream = new CryptoStream(encryptStream, GenerateDESCryptoServiceProvider(encryptKey).CreateEncryptor(), CryptoStreamMode.Write);

        try
        {
            encStream.Write(bytIn, 0, bytIn.Length);
            encStream.FlushFinalBlock();
            stringEncrypted = Convert.ToBase64String(encryptStream.ToArray(), 0, (int)encryptStream.Length);
        }
        catch
        {
            return "";
        }
        finally
        {
            encryptStream.Close();
            encStream.Close();
        }

        return stringEncrypted;
    }

    /// <summary>
    /// 通过密钥讲内容解密
    /// </summary>
    /// <param name="stringToDecrypt">要解密的字符串</param>
    /// <param name="encryptKey">密钥</param>
    /// <returns></returns>
    public static string DecryptString(string stringToDecrypt, string encryptKey)
    {
        if (String.IsNullOrEmpty(stringToDecrypt))
        {
            return "";
        }

        string stringDecrypted = string.Empty;
        byte[] bytIn = Convert.FromBase64String(stringToDecrypt.Replace(" ", "+"));
        MemoryStream decryptStream = new MemoryStream();
        CryptoStream encStream = new CryptoStream(decryptStream, GenerateDESCryptoServiceProvider(encryptKey).CreateDecryptor(), CryptoStreamMode.Write);

        try
        {
            encStream.Write(bytIn, 0, bytIn.Length);
            encStream.FlushFinalBlock();
            stringDecrypted = Encoding.Default.GetString(decryptStream.ToArray());
        }
        catch
        {
            return "";
        }
        finally
        {
            decryptStream.Close();
            encStream.Close();
        }

        return stringDecrypted;
    }

    private static DESCryptoServiceProvider GenerateDESCryptoServiceProvider(string key)
    {
        DESCryptoServiceProvider dCrypter = new DESCryptoServiceProvider();

        string sTemp;
        if (dCrypter.LegalKeySizes.Length > 0)
        {
            int moreSize = dCrypter.LegalKeySizes[0].MinSize;
            while (key.Length > 8)
            {
                key = key.Substring(0, 8);
            }
            sTemp = key.PadRight(moreSize / 8, ' ');
        }
        else
        {
            sTemp = key;
        }
        byte[] bytKey = UTF8Encoding.UTF8.GetBytes(sTemp);

        dCrypter.Key = bytKey;
        dCrypter.IV = bytKey;

        return dCrypter;
    }

    #endregion

    #region MD5加密

    /// <summary>
    /// 字符串MD5加密
    /// </summary>
    /// <param name="str"></param>
    /// <returns>返回大写32位MD5值</returns>
    public static string GetMD5String(string str)
    {
        byte[] buffer = Encoding.UTF8.GetBytes(str);

        return MD5String(buffer);
    }

    /// <summary>
    /// 流MD5加密
    /// </summary>
    /// <param name="stream"></param>
    /// <returns></returns>
    public static string GetMD5Stream(Stream stream)
    {
        byte[] buffer = new byte[stream.Length];
        stream.Read(buffer, 0, buffer.Length);
        return MD5String(buffer);
    }

    /// <summary>
    /// 文件MD5加密
    /// </summary>
    /// <param name="path"></param>
    /// <returns>返回大写32位MD5值</returns>
    public static string GetMD5File(string path)
    {
        if (File.Exists(path))
        {
            using (FileStream fs = new FileStream(path, FileMode.Open))
            {
                return GetMD5Stream(fs);
            }
        }
        else
        {
            return string.Empty;
        }
    }

    private static string MD5String(byte[] buffer)
    {
        MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
        byte[] cryptBuffer = md5.ComputeHash(buffer);
        StringBuilder sb = new StringBuilder();
        foreach (byte item in cryptBuffer)
        {
            sb.Append(item.ToString("X2"));
        }
        return sb.ToString();
    }

    #endregion

    //public static string GetNugetVersion(string start = null, bool pre = false)
    //{
    //    var Cache = GlobalServices.GetRequiredService<IDistributedCache>() as IDistributedCache;
    //    if (Cache.TryGetValue("nugetversion", out NugetInfo rv) == false || rv == null)
    //    {
    //        NugetInfo v = APIHelper.CallAPI<NugetInfo>($"https://api-v2v3search-0.nuget.org/query?q=WalkingTec.Mvvm.Mvc&prerelease={pre.ToString().ToLower()}").Result;
    //        var data = v;
    //        Cache.Add("nugetversion", data, new DistributedCacheEntryOptions()
    //        {
    //            SlidingExpiration = new TimeSpan(0, 0, 36000)
    //        });
    //        rv = data;
    //    }

    //    if (string.IsNullOrEmpty(start))
    //    {
    //        return rv.data[0]?.version;
    //    }
    //    else
    //    {
    //        return rv.data[0].versions.Select(x => x.version).Where(x => x.StartsWith(start)).Last();
    //    }
    //}

    /// <summary>
    /// ASCII转String
    /// </summary>
    /// <param name="asciiCode"></param>
    /// <returns></returns>
    public static string AsciiToString(int asciiCode)
    {
        if (asciiCode >= 0 && asciiCode <= 255)
        {
            ASCIIEncoding aSCIIEncoding = new ASCIIEncoding();
            byte[] byteArr = new byte[] { (byte)asciiCode };
            string str = aSCIIEncoding.GetString(byteArr);
            return str;
        }
        else
        {
            return "ASCII码不正确";
        }
    }

    /// <summary>
    /// 生成某个exe程序的快捷方式
    /// </summary>
    /// <param name="lnkFilePath">快捷方式的路径，例如：C:\Users\Public\Desktop\abc.lnk <para>例如：{Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory)}\\XXX.lnk</para></param>
    /// <param name="targetPath">exe程序的全路径（可执行文件的路径）<para>{AppDomain.CurrentDomain.BaseDirectory}XX.exe</para></param>
    /// <param name="args">快捷方式的快捷键</param>
    /// <returns></returns>
    public static bool CreateShortcut(string lnkFilePath, string targetPath, string args = "")
    {
        try
        {
            var shellType = Type.GetTypeFromProgID("WScript.Shell");
            dynamic shell = Activator.CreateInstance(shellType);
            var shortcut = shell.CreateShortcut(lnkFilePath);
            //shortcut.TargetPath = Assembly.GetEntryAssembly().Location;       //这是当前程序的路径
            shortcut.TargetPath = targetPath;
            shortcut.Arguments = args;
            shortcut.WorkingDirectory = AppDomain.CurrentDomain.SetupInformation.ApplicationBase;
            shortcut.Save();
            return true;
        }
        catch (Exception)
        {
            return false;
        }
    }

    #region model转换

    /// <summary>
    /// 模型转换
    /// </summary>
    /// <typeparam name="InT">被转换的类型</typeparam>
    /// <typeparam name="OutT">转换成的类型</typeparam>
    /// <param name="model">被转换的model</param>
    /// <returns></returns>
    public static OutT ModelConverter<InT, OutT>(InT model)
    {
        Type InType = typeof(InT);
        InT inTModel = model;

        Type OutType = typeof(OutT);
        OutT outTModel = (OutT)Activator.CreateInstance(OutType);

        //通过反射去遍历属性
        foreach (PropertyInfo inProperty in InType.GetProperties())
        {
            foreach (PropertyInfo OutProperty in OutType.GetProperties())
            {
                if (inProperty.Name == OutProperty.Name && inProperty.PropertyType == OutProperty.PropertyType)
                {
                    OutProperty.SetValue(outTModel, inProperty.GetValue(inTModel));
                }
            }
        }

        return outTModel;
    }

    /// <summary>
    /// 模型转换
    /// </summary>
    /// <typeparam name="InT">被转换的类型</typeparam>
    /// <typeparam name="OutT">转换成的类型</typeparam>
    /// <param name="json">需要转换的json</param>
    /// <returns></returns>
    public static OutT ModelConverter<InT, OutT>(string json)
    {
        Type InType = typeof(InT);
        InT inTModel = System.Text.Json.JsonSerializer.Deserialize<InT>(json);

        Type OutType = typeof(OutT);
        OutT outTModel = (OutT)Activator.CreateInstance(OutType);

        //通过反射去遍历属性
        foreach (PropertyInfo inProperty in InType.GetProperties())
        {
            foreach (PropertyInfo OutProperty in OutType.GetProperties())
            {
                if (inProperty.Name == OutProperty.Name && inProperty.PropertyType == OutProperty.PropertyType)
                {
                    OutProperty.SetValue(outTModel, inProperty.GetValue(inTModel));
                }
            }
        }

        return outTModel;
    }

    #endregion
}